package com.luo.demo.oidc.combo.service;

import com.luo.sc.oidc.authserver.utils.HttpContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * 手机号发送验证码 - 服务
 *
 * @author luohq
 * @version 1.0.0
 * @date 2022-03-07 11:08
 */
@Service
@Slf4j
public class PhoneSmsCodeService {

    private final String CACHE_SMSCODE_PREFIX = "smscode-";

    /**
     * 发送验证码
     *
     * @param phoneNo
     */
    public void sendSmsCode(String phoneNo) {
        //发送验证码
        String smsCode = this.randomSmscode();
        log.info("[MOCK]send smsCode: {}", smsCode);

        //在缓存中（暂使用session）中记录手机号与验证码关系，且需设置对应的缓存失效时间
        HttpContextUtils.getExistSession().setAttribute(this.convertCacheKey(phoneNo), smsCode);
    }

    /**
     * 验证手机号和验证码
     *
     * @param phoneNo
     * @param smsCode
     */
    public void validateSmsCode(String phoneNo, String smsCode) {
        //获取缓存中的验证码
        String smsCodeInCache = (String) HttpContextUtils.getExistSession().getAttribute(this.convertCacheKey(phoneNo));
        if (null == smsCodeInCache) {
            log.error("PhoneNo:{} doesn't have correspond smsCode", phoneNo);
            throw new UsernameNotFoundException("请先点击发送验证码");
        }
        if (!smsCode.equals(smsCodeInCache)) {
            log.error("phoneNo login parameter smsCode:{} is different form smsCodeInCache:{}", smsCode, smsCodeInCache);
            throw new UsernameNotFoundException("验证码错误");
        }

        //验证成功后清除验证码
        HttpContextUtils.getExistSession().removeAttribute(this.convertCacheKey(phoneNo));
    }


    /**
     * 生成缓存KEY
     *
     * @param phoneNo 手机号
     * @return 缓存KEY
     */
    private String convertCacheKey(String phoneNo) {
        return new StringBuilder(CACHE_SMSCODE_PREFIX)
                .append(phoneNo)
                .toString();
    }

    /**
     * MOCK生成验证码
     *
     * @return 验证码
     */
    private String randomSmscode() {
        return IntStream.range(0, 6)
                .mapToObj(index -> String.valueOf(new Random().nextInt(10)))
                .collect(Collectors.joining());
    }
}
